﻿using Common.Framework.Core.Common;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Minio;

namespace Common.Framework.Core.Minio
{
    /// <summary>
    /// 接口文档: http://docs.minio.org.cn/docs/master/dotnet-client-api-reference
    /// </summary>
    public class UrlService : IMinioService
    {
        private readonly MinioClient minioClient;
        private readonly UrlConfig minioConfig;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="minioConfig"></param>
        /// <param name="minioClient"></param>
        public UrlService(IOptions<UrlConfig> minioConfig, MinioClient minioClient)
        {
            this.minioConfig = minioConfig.Value;
            this.minioClient = minioClient;
        }

        /// <summary>
        /// 上传文件,每次只能上传一个文件.
        /// </summary>
        /// <param name="file"></param>
        /// <param name="filePath">因为minio区分目录是在访问路径上区分的,比如:thridparty/a/b/c.jpg,所以filepath=a/b.注意:filePath不带前后斜杠</param>
        /// <param name="fileName">文件名称.注意:fileName不带前面的斜杠</param>
        /// <param name="removeOldFileName">需要删除的旧文件,为空则不删</param>
        /// <returns></returns>
        public async Task<ServiceResult<MinioFileModel>> UploadAsync(FormFileCollection file, string filePath = null, string newFileName = null, string removeOldFileName = "")
        {
            return await UploadAsync(file[0], filePath, newFileName, removeOldFileName);
        }

        /// <summary>
        /// 上传文件,每次只能上传一个文件
        /// </summary>
        /// <param name="file"></param>
        /// <param name="filePath"></param>
        /// <param name="newFileName"></param>
        /// <param name="removeOldFileName"></param>
        /// <returns></returns>
        public async Task<ServiceResult<MinioFileModel>> UploadAsync(IFormFile file, string filePath = null, string newFileName = null, string removeOldFileName = "")
        {
            return await UploadStreamAsync(file.OpenReadStream(), file.FileName, file.Length, file.ContentType, filePath, newFileName, removeOldFileName);
        }

        /// <summary>
        /// 上传文件,每次只能上传一个文件,只接受文件流
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="oldFileName"></param>
        /// <param name="fileLength"></param>
        /// <param name="fileContentType"></param>
        /// <param name="filePath"></param>
        /// <param name="newFileName"></param>
        /// <param name="removeOldFileName"></param>
        /// <returns></returns>
        public async Task<ServiceResult<MinioFileModel>> UploadStreamAsync(Stream stream, string oldFileName, long fileLength, string fileContentType, string filePath = null, string newFileName = null, string removeOldFileName = "")
        {
            try
            {

          
            ServiceResult<MinioFileModel> result = new ServiceResult<MinioFileModel>();

            //如果旧文件名不为空,则先删除旧文件
            if (!string.IsNullOrWhiteSpace(removeOldFileName))
            {
                RemoveObjectArgs removeArgs = new RemoveObjectArgs()
                 .WithBucket(minioConfig.BucketName)
                 .WithObject(removeOldFileName);
                await minioClient.RemoveObjectAsync(removeArgs);
            }

            string bucketName = minioConfig.BucketName;
            //新的文件名称
            string tmpNewFileName = newFileName == null ? CreateNewFileName(bucketName, oldFileName) : newFileName;
            //拼接上子目录后的文件名称
            string lastFileName = filePath == null ? tmpNewFileName : $"{filePath}/{tmpNewFileName}";

            PutObjectArgs args = new PutObjectArgs()
                .WithBucket(bucketName)
                .WithObject(lastFileName)
                .WithStreamData(stream)
                .WithObjectSize(fileLength)
                .WithContentType(fileContentType);

            await minioClient.PutObjectAsync(args);

            MinioFileModel minioFileModel = new MinioFileModel
            {
                FilePath = $"{filePath}", //返回的字符串不带文件名称,且不带bucketname
                OriginalFileName = oldFileName,
                StorageFileName = tmpNewFileName,
            };
            result.Data = minioFileModel;

            return result;
            }
            catch (Exception ex)
            {

                throw;
            }
        }
        /// <summary>
        /// 删除一个文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public async Task<ServiceResult<bool>> RemoveObjectAsync(string fileName)
        {
            ServiceResult<bool> result = new ServiceResult<bool>();

            RemoveObjectArgs args = new RemoveObjectArgs()
                .WithBucket(minioConfig.BucketName)
                .WithObject(fileName);

            await minioClient.RemoveObjectAsync(args);

            result.Data = true;
            return result;
        }

        /// <summary>
        /// 删除多个文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public async Task<ServiceResult<bool>> RemoveObjectsAsync(List<string> fileNames)
        {
            ServiceResult<bool> result = new ServiceResult<bool>();

            RemoveObjectsArgs args = new RemoveObjectsArgs()
                .WithBucket(minioConfig.BucketName)
                .WithObjects(fileNames);

            await minioClient.RemoveObjectsAsync(args);

            result.Data = true;
            return result;
        }

        private string CreateNewFileName(string bucketName, string oldFileName)
        {
            var dt = Guid.NewGuid().ToString().Replace("-", "").Substring(10) + DateTimeOffset.Now.ToUnixTimeSeconds();
            var extensions = Path.GetExtension(oldFileName);
            var newFileName = $"{bucketName}-{dt}{extensions}";
            return newFileName;
        }
    }
}
